import { defineStore } from 'pinia'
import SockJs from "sockjs-client/dist/sockjs.min.js"
import Stomp from "stompjs"
import subscribeHandlers from "@/staticDatas/subscribeHandlers"
import Cookie from '@/plugins/cookie'

export const useSocketPinia = defineStore('socket', {
  // 推荐使用 完整类型推断的箭头函数
  state: () => ({
    socket: null as any as WebSocket,
    stomp: null as any as Stomp.Client,
    subscriptions: subscribeHandlers,
  }),
  actions: {
    SOCKET_CREATE(url: string = '/socket/ws'): void {
      if (this.stomp === null || !this.stomp.connected) {
        // 可能websocket为open状态但是stomp未连接
        if (this.stomp !== null && this.socket.readyState === SockJs.OPEN)
          this.stomp.disconnect(() => this.SOCKET_CONNECT(url))
        else if (this.stomp !== null && this.socket.readyState === SockJs.CONNECTING) {
          console.log('正在建立websocket连接');
          return
        } else this.SOCKET_CONNECT(url);
      }
    },
    SOCKET_CONNECT(url: string = '/socket/ws'): void {
      if (this.stomp?.connected) return;
      this.socket = new SockJs(url);
      this.stomp = Stomp.over(this.socket);
      this.stomp.debug = () => { };
      this.stomp.heartbeat.outgoing = 15000;
      const token: string = Cookie.getCookie('token');
      this.stomp.connect(
        { token },
        () => {
          this.subscriptions.length &&
            this.subscriptions.forEach(item => {
              if (typeof item.url === 'string')
                this.stomp.subscribe(item.url, (res) => item.callback(res), item.headers ? item.headers : {});
              else
                this.stomp.subscribe(item.url({ token }), (res) => item.callback(res), item.headers ? item.headers : {});
            })
        },
        //第一次连接失败和连接后断开连接都会调用这个函数
        error => {
          console.log(error);
          setTimeout(() => {
            console.log('开始重连');
            this.SOCKET_CREATE();
          }, 3000);
        })
    },
    SOCKET_SEND(payload: {
      url: string;
      data: string;
      headers?: {};
    }): void {
      if (this.stomp?.connected)
        this.stomp.send(
          payload.url,
          payload.headers ? payload.headers : {},
          payload.data,
        );
    },
    SOCKET_SUBSRCIBE(payload: {
      url: string;
      callback: (...args: any[]) => any;
      headers?: {};
    }): Promise<boolean> {
      return new Promise<boolean>(resolve => {
        if (this.stomp?.connected) {
          this.stomp.subscribe(payload.url, payload.callback, payload.headers ? payload.headers : {});
          this.subscriptions.push(payload);
          resolve(true);
        } else {
          resolve(false);
          console.log('等待连接成功');
        }
      })
    },
    SOCKET_UNSUBSRCIBE(payload: {
      id: string;
      url: string;
      args?: any;
    }): void {
      if (this.stomp?.connected) {
        this.stomp.unsubscribe(payload.id);
        const index: number = this.subscriptions.findIndex(item => {
          if (typeof item.url === 'string') return item.url === payload.url;
          else if (payload?.args) return item.url(payload.args) === payload.url
        });
        this.subscriptions.splice(index, 1);
      }
    },
    SOCKET_CLOSE(payload: {
      callback: (...args: any[]) => any;
      headers?: {};
    }): void {
      if (this.stomp?.connected)
        this.stomp.disconnect(payload.callback, payload.headers ? payload.headers : {});
    },
  },
})